#ifndef HEADER_H
#define HEADER_H

#include<vector>
#include<cstring>

using namespace std;


class Masina
{
protected:
	vector<char*> dotari;
	vector<char*> motorizare;
	vector<char*> dimensiune;
	vector<char*> culoare;
	vector<char*> transmisie;
public:
	Masina(void);
	virtual void Insert_car()=0;
	~Masina()
	{
	dotari.pop_back();
	motorizare.pop_back();
	dimensiune.pop_back();
	culoare.pop_back();
	transmisie.pop_back();
	}
};

class Sedan:public Masina
{
public:
	Sedan(void);
	void Insert_car(char* dotari,char* motorizare,char* dimensiune,char *culoare,char *transmisie)
	{
		this->culoare.push_back(culoare);
		this->dimensiune.push_back(dimensiune);
		this->dotari.push_back(dotari);
		this->motorizare.push_back(motorizare);
		this->transmisie.push_back(transmisie);
	}
};
class Coupe:public Masina
{
public:
	void Insert_car(char* dotari,char* motorizare,char* dimensiune,char *culoare,char *transmisie)
	{
		this->culoare.push_back(culoare);
		this->dimensiune.push_back(dimensiune);
		this->dotari.push_back(dotari);
		this->motorizare.push_back(motorizare);
		this->transmisie.push_back(transmisie);
	}
};

class Mini:public Masina
{
public:
	void Insert_car(char* dotari,char* motorizare,char* dimensiune,char *culoare,char *transmisie)
	{
		this->culoare.push_back(culoare);
		this->dimensiune.push_back(dimensiune);
		this->dotari.push_back(dotari);
		this->motorizare.push_back(motorizare);
		this->transmisie.push_back(transmisie);
	}
};

class CarFactory //--------AbstractFactory Pettern------
{    
public:
    enum CAR_FACTORIES
    {
        Sedan,
        Coupe,
        Mini,
    };

    virtual Masina* GetMasina() = 0;

    static CarFactory* CreateFactory(CAR_FACTORIES factory);    
};

class Singleton// ------Singleton Pattern -------
{
private:
    static bool exista_masina;
    static Singleton *single;
    Singleton()
    {
       exista_masina=true;
    }
public:
    static Singleton* getInstance();
    void method();
    ~Singleton()
    {
        exista_masina = false;
    }
};

bool Singleton::exista_masina = false;
Singleton* Singleton::single = NULL;
Singleton* Singleton::getInstance()
{
    if(! exista_masina)
    {
        single = new Singleton();
        exista_masina = true;
        return single;
    }
    else
    {
        return single;
    }
}

class ObjectPool // ----- ObjectPool Pattern -----
{
    private:
        std::vector<Masina*> resources;
        
        static ObjectPool* instance;
        ObjectPool() {}
 
    public:
     
        static ObjectPool* getInstance()
        {
            if (instance == 0)
            {
                instance = new ObjectPool;
            }
            return instance;
        }
 
       
        Masina* getResource()
        {
            if (resources.empty())
            {
                std::cout << "Creating new." << std::endl;
                
            }
            else
            {
                std::cout << "Reusing existing." << std::endl;
                Masina* resource = resources.front();
                resources.pop_back();
                return resource;
            }
        }
 
       
        void returnResource(Masina* object)
        {
			
            resources.push_back(object);
        }
};
 
ObjectPool* ObjectPool::instance = 0;
 


class Client
{
private:
	Masina *A[20];
	char *Name;
	int Age;
	std::vector<Masina*> lista;
public:
	Client(){};
	void Add_Car(Masina *m)
	{

		this->lista.push_back(m);
	}
	void Delete_Car(Masina *m)
	{
	
		for(int i=0;i<this->lista.size();i++)
			if(m==lista[i])
				lista[i]->~Masina();
				
	}


};
#endif
/*
Definire client cu membrii nume, varsta si lista masini - 0.5
Definire masina abstracta si cele 3 tipuri de masini (Seddan, Coupe, Mini) cu membrii: dotari, motorizare, dimensiune, culoare si transmisie - 0.5

Introducere masina - 0.5
Adaugare masina client - 0.5

Folosire AbstractFactory Pettern - 2
Folosire Singleton Pattern - 2
Folosire ObjectPool Pattrn - 2

Fisier info cu descriere corecta - 1

+ Bonus:
    Stergere masina - 1
    Diagrama sequence - 1
    Diagrama communication
*/